package com.web_bloks.widget.client;

//import com.web_bloks.system.Logger;
import java.util.Iterator;
import java.util.Vector;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.Widget;

/**
 * 
 * @author Jean-Lou Dupont
 *
 */
public class RatingWidget extends Composite 
	implements ClickListener, MouseListener {

	FlexTable panel = null;
	
	HorizontalPanel[] cells = null;
	
	Image[] images = null;

	int rating = 0;
	boolean rated = false;
	boolean lockAfterRating = false;
	
	Vector<RatingWidgetListener> listeners = new Vector<RatingWidgetListener>();
	
	/**
	 * Constructor
	 */
	public RatingWidget() {
		super();
	
		panel = new FlexTable();
		
		initWidget( panel );
		
		cells = new HorizontalPanel[5];
		
		WidgetImageBundle bundle = (WidgetImageBundle) GWT.create( WidgetImageBundle.class );
		
		images = new Image[10];
		
		for(int i=0;i<5;i++){
			images[i*2]   = bundle.star_n().createImage();
			images[i*2+1]   = bundle.star_y().createImage();
			
			cells[i] = new HorizontalPanel();
			panel.setWidget(0, i, cells[i]);
			
			cells[i].add(images[i*2]);
			cells[i].add(images[i*2+1]);

			images[i*2].addClickListener(this);
			images[i*2].addMouseListener(this);

			images[i*2+1].addClickListener(this);
			images[i*2+1].addMouseListener(this);
		}
		
		clearStars();
	}
	
	public int getRating() {
		return this.rating;
	}
	
	public void setRating(int rating) {
		
		if (rated && lockAfterRating)
			return;
		
		this.rating = rating;
		this.rated = true;
		
		setStars(rating);
		
		notifyListeners( );
	}
	public void setLockAfterRating(boolean lock) {
		this.lockAfterRating = lock;
	}
	
	/**
	 * Only integers between [0;5] admitted
	 */
	protected void setStars(int rating) {
		
		clearStars();

		if (rating == 0)
			return;
		
		if (rating>5 || rating<0)
			throw new RuntimeException("invalid rating");

		int i = rating-1;
		
		do {
			images[i*2].setVisible(false);
			images[i*2+1].setVisible(true);
			i--;
		} while(i>=0);

	}
	
	public void clearStars() {
		for (int i=0;i<5;i++) {
			images[i*2].setVisible(true);
			images[i*2+1].setVisible(false);
		}
	}
	
	public void onClick(Widget sender) {

		if (rated && lockAfterRating)
			return;

		int r = extractRating( sender );
		
		setRating(r);

		//Logger.logDebug(this.getClass().toString()+".onClick, rating["+rating+"]");
	}

	public void onMouseEnter(Widget sender){
		
		if (rated && lockAfterRating)
			return;
		
		int r = extractRating( sender );
		
		setStars(r);
	}
	
	public void onMouseLeave(Widget sender){

		if (rated && lockAfterRating)
			return;
		
		setStars(rating);
	}
	
	public void onMouseDown(Widget sender, int x, int y){}
	public void onMouseMove(Widget sender, int x, int y){}
	public void onMouseUp(Widget sender, int x, int y){}
	
	/*****************************************
	 * HELPERS
	 *****************************************/
	protected int extractRating(Widget w) {
		
		int rating = 0;
		
		for (int i=0;i<5;i++) {
			if ( w == images[i*2] || w == images[i*2+1]) {
				rating = i+1;
				break;
			}
		}
		
		return rating;
	}
	
	/*****************************************
	 * Listeners 
	 *****************************************/
	public void addRatingListener(RatingWidgetListener listener) {
		listeners.add(listener);
	}
	public void removeRatingListener(RatingWidgetListener listener) {
		listeners.remove(listener);
	}
	protected void notifyListeners() {
		
		Iterator<RatingWidgetListener> it = this.listeners.iterator();
		while (it.hasNext()) {
			Object o = it.next ();
		    ((RatingWidgetListener) o).onRatingChanged( this );
		}
	}

}//END